package com.freeheart.aop.log.log;

import com.freeheart.aop.log.LogInterceptor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;


/**
 * 对使用@Log在类和方法上的情况进行日志增强支持（AspectJ风格的Aop）
 * @author EmperorHeart
 */
@Aspect
public class LogAspect {
    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    private final LogInterceptor logInterceptor;

    public LogAspect(LogInterceptor logInterceptor){
        this.logInterceptor = logInterceptor;
    }

    /**
     * 注解Log的切点表达式
     * @annotation 表示使用这个注解的方法，方法是一个切点
     * @within 表示使用这个注解的类，类下的所有方法是一个切点
     */
    @Pointcut("@annotation(com.freeheart.aop.log.log.Log) || @within(com.freeheart.aop.log.log.Log)")
    public void logPointCut() {
    }

    @Around("logPointCut()")
    public Object aroundControllerAspect(ProceedingJoinPoint point) throws Throwable {
        Method method = null;
        try {
            Signature signature = point.getSignature();
            if (signature instanceof MethodSignature methodSignature) {
                 method = methodSignature.getMethod();
                if (method.isAnnotationPresent(LogIgnore.class) || method.getDeclaringClass().isAnnotationPresent(LogIgnore.class)) {
                    return point.proceed();
                }
            }
        } catch (Exception e) {
            logger.warn("切面异常", e);
        }


        return logInterceptor.process(method, point.getArgs(), ()-> {
            try {
                return point.proceed();
            } catch (Throwable throwable) {
                logger.error("执行切面异常：{}", throwable.getMessage(), throwable);
                return new Exception("切面异常");
            }
        });


    }


}
